package rollercoaster.railway;

import rollercoaster.commons.Vertex3D;
import rollercoaster.commons.Vertex4D;
import rollercoaster.commons.interfaces.ICurve3D;
import rollercoaster.commons.interfaces.ITrajectory;
import rollercoaster.commons.interfaces.Surface3D;
import rollercoaster.railway.utils.ArrayUtils;
import rollercoaster.railway.utils.VertexUtils;



public class Tube implements Surface3D{

	private ITrajectory trajectory;
	private static final float EPSILON = 0.01f;
	private ICurve3D section;
	private Vertex3D relativetranslation;
	
	
	public Tube(ITrajectory trajectory, ICurve3D section, Vertex3D relativetranslation) {
		super();
		this.trajectory = trajectory;
		this.section = section;
		this.relativetranslation = relativetranslation;
	}

	public Vertex3D sigma(float u, float v) {
		
		Vertex3D val=section.gamma(u);
		Vertex4D vector = new Vertex4D(val.getX()+ relativetranslation.getX(), val.getY() + relativetranslation.getY(),val.getZ()+ relativetranslation.getZ(), 1.0f);
		float[][] matrix = new float[4][4];
		trajectory.getTransformMatrix(matrix, v);
		/*
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix.length; j++) {
				System.out.print(matrix[i][j]+" ");
			}
			System.out.println();
		}*/
		float[] cartesianvector = ArrayUtils.matrixByVector(matrix, vector.getCoordinates());
		
		return new Vertex3D(cartesianvector[0], cartesianvector[1], cartesianvector[2]);
	}

	public Vertex3D dSigmadu(float u, float v) {
		
		Vertex3D v1 = sigma(u-EPSILON, v);
		Vertex3D v2 = sigma(u+EPSILON, v);
		
		Vertex3D d = new Vertex3D((v2.getX() - v1.getX())/(2*EPSILON), (v2.getY() - v1.getY())/(2*EPSILON), (v2.getZ() - v1.getZ())/(2*EPSILON));
		
		
		return d;
	}

	public Vertex3D dSigmadv(float u, float v) {
		
		Vertex3D v1 = sigma(u, v-EPSILON);
		Vertex3D v2 = sigma(u, v+EPSILON);
		
		Vertex3D d = new Vertex3D((v2.getX() - v1.getX())/(2*EPSILON), (v2.getY() - v1.getY())/(2*EPSILON), (v2.getZ() - v1.getZ())/(2*EPSILON));
		
		
		return d;
	}

	public Vertex3D getNormal(float u, float v) {
		
		Vertex3D normal = VertexUtils.crossProduct(dSigmadu(u, v), dSigmadv(u, v));
		VertexUtils.normalizeVector(normal);
		return normal;
	}

	public float getStartUPoint() {
		return section.getStartPoint();
	}

	public float getEndUPoint() {
		return section.getEndPoint();
	}

	public float getStartVPoint() {
		return trajectory.getBase().getStartPoint();
	}

	public float getEndVPoint() {
		return trajectory.getBase().getEndPoint();
	}

	public ITrajectory getTrajectory() {
		return trajectory;
	}

	
	
}
